/* -------------------------------------------------------------------------- *
   TestWinUnit - Maria Blees (maria.blees@microsoft.com)

   File: TestRunnerTest.cpp

   This file contains tests for the TestRunner class.
 * -------------------------------------------------------------------------- */
#include "WinUnit.h"

#include "TestRunner.h"
#include "MockTestcontainer.h"
#include "MockLogger.h"

using namespace WinUnitLib;

BEGIN_TEST(TestRunnerFailsButDoesNotCrashOnDivideByZero)
{
    MockLogger logger;
    MockTestContainer testContainer("DivideByZero");
    TestRunner testRunner(logger);

    TestResults testResults = testRunner.ProcessTests(testContainer);

    WIN_ASSERT_ZERO(testResults.SucceededCount);
    WIN_ASSERT_EQUAL(1U, testResults.TotalRunCount);

    WIN_ASSERT_EQUAL(1, logger.OutputTestNamePreTestCalled);
    WIN_ASSERT_EQUAL(1, logger.OutputTestErrorCalled);
    WIN_TRACE("INFO: Next line should indicate divide-by-zero failure:\n");
    WIN_TRACE(L"OUTPUT: %s\n", logger.OutputTestError_message);
    WIN_ASSERT_EQUAL(1, logger.OutputTestNamePostTestCalled); 
}
END_TEST

BEGIN_TEST(TestRunnerRunsFailingTest)
{
    MockLogger logger;
    MockTestContainer testContainer("FailingTest");
    TestRunner testRunner(logger);

    TestResults testResults = testRunner.ProcessTests(testContainer);

    WIN_ASSERT_ZERO(testResults.SucceededCount);
    WIN_ASSERT_EQUAL(1U, testResults.TotalRunCount);

    WIN_ASSERT_EQUAL(1, logger.OutputTestNamePreTestCalled);
    WIN_ASSERT_EQUAL(1, logger.OutputTestErrorCalled);
    WIN_TRACE("INFO: Next line should indicate that \"FailingTest\" failed:\n");
    WIN_TRACE(L"OUTPUT: %s\n", logger.OutputTestError_message);
    WIN_ASSERT_EQUAL(1, logger.OutputTestNamePostTestCalled); 
}
END_TEST

BEGIN_TEST(TestRunnerRunsSuccessfulTest)
{
    MockLogger logger;
    MockTestContainer testContainer("SuccessfulTest");
    TestRunner testRunner(logger);

    TestResults testResults = testRunner.ProcessTests(testContainer);

    WIN_ASSERT_EQUAL(1U, testResults.SucceededCount);
    WIN_ASSERT_EQUAL(1U, testResults.TotalRunCount);

    WIN_ASSERT_EQUAL(1, logger.OutputTestNamePreTestCalled);
    WIN_ASSERT_ZERO(logger.OutputTestErrorCalled);
    WIN_ASSERT_EQUAL(1, logger.OutputTestNamePostTestCalled);
}
END_TEST

#pragma region Testing StringCompareCaseInsensitiveN

// This section doesn't use the naming convention of the rest of the tests--
// Function name was unique enough so it's its own prefix.
// (Here you can see some examples of really long test names!)

// Loop ends when i == n - 1
BEGIN_TEST(StringCompareCaseInsensitiveNShouldBeZeroForString1LongerThanString2AndNShorterThanBothWithFirstNCharactersSame)
{
    char* string1 = "food";
    TCHAR* string2 = _T("foobar");

    int comparison = TestRunner::StringCompareCaseInsensitiveN(string1, string2, 3);

    WIN_ASSERT_TRUE(comparison == 0);
}
END_TEST

// Loop ends when i == n - 1
BEGIN_TEST(StringCompareCaseInsensitiveNShouldBeZeroForString2LongerThanString1AndNShorterThanBothWithFirstNCharactersSame)
{
    char* string1 = "foobar";
    TCHAR* string2 = _T("food");

    int comparison = TestRunner::StringCompareCaseInsensitiveN(string1, string2, 3);

    WIN_ASSERT_TRUE(comparison == 0);
}
END_TEST

// Loop ends when (int)string1[i] != (int)string2[i] (i < n - 1)
BEGIN_TEST(StringCompareCaseInsensitiveNShouldBeCorrectForString1LongerThanString2AndNShorterThanBothWithFirstNCharactersDifferent)
{
    char* string1 = "food";
    TCHAR* string2 = _T("fobar");

    int comparison = TestRunner::StringCompareCaseInsensitiveN(string1, string2, 3);

    WIN_ASSERT_TRUE(comparison > 0);
}
END_TEST

// Loop ends when (int)string1[i] != (int)string2[i] (i < n - 1)
BEGIN_TEST(StringCompareCaseInsensitiveNShouldBeCorrectForString2LongerThanString1AndNShorterThanBothWithFirstNCharactersDifferent)
{
    char* string1 = "fobar";
    TCHAR* string2 = _T("food");

    int comparison = TestRunner::StringCompareCaseInsensitiveN(string1, string2, 3);

    WIN_ASSERT_TRUE(comparison < 0);
}
END_TEST

// Loop ends when string1[i] == '\0' (i < n - 1)
BEGIN_TEST(StringCompareCaseInsensitiveNShouldBeCorrectForString1ShorterThanString2AndNLongerThanString1AndString1SubstringOfString2)
{
    char* string1 = "foo";
    TCHAR* string2 = _T("foobar");
    size_t n = 5;

    int comparison = TestRunner::StringCompareCaseInsensitiveN(string1, string2, n);

    WIN_ASSERT_TRUE(comparison < 0);
}
END_TEST

// Loop ends when i == n - 1 (result: 0)
BEGIN_TEST(StringCompareCaseInsensitiveNShouldBeZeroForString1ShorterThanString2AndNLengthOfString1AndString1SubstringOfString2)
{
    char* string1 = "foo";
    TCHAR* string2 = _T("foobar");
    size_t n = 3;

    int comparison = TestRunner::StringCompareCaseInsensitiveN(string1, string2, n);

    WIN_ASSERT_TRUE(comparison == 0);
}
END_TEST

// Loop ends when (int)string1[i] != (int)string2[i] (i < n - 1)
BEGIN_TEST(StringCompareCaseInsensitiveNShouldBeCorrectForString1ShorterThanString2AndNLongerThanString1AndString1NotSubstringOfString2)
{
    char* string1 = "foo";
    TCHAR* string2 = _T("barfoo");
    size_t n = 5;

    int comparison = TestRunner::StringCompareCaseInsensitiveN(string1, string2, n);

    WIN_ASSERT_TRUE(comparison > 0);
}
END_TEST

// Loop ends when string2[i] == '\0' (return: > 0)
BEGIN_TEST(StringCompareCaseInsensitiveNShouldBeCorrectForString2ShorterThanString1AndNLongerThanString2AndString2SubstringOfString1)
{
    char* string1 = "foobar";
    TCHAR* string2 = _T("foo");
    size_t n = 5;

    int comparison = TestRunner::StringCompareCaseInsensitiveN(string1, string2, n);

    WIN_ASSERT_TRUE(comparison > 0);
}
END_TEST

// Loop ends when (int)string1[i] != (int)string2[i]
BEGIN_TEST(StringCompareCaseInsensitiveNShouldBeCorrectForString2ShorterThanString1AndNLongerThanString2AndString2NotSubstringOfString1)
{
    char* string1 = "barfoo";
    TCHAR* string2 = _T("foo");
    size_t n = 5;

    int comparison = TestRunner::StringCompareCaseInsensitiveN(string1, string2, n);

    WIN_ASSERT_TRUE(comparison < 0);
}
END_TEST

// Loop ends when string1[i] == '\0' (return: 0)
BEGIN_TEST(StringCompareCaseInsensitiveNShouldBeCorrectForNLongerThanBothString1AndString2AndTwoStringsIdentical)
{
    char* string1 = "foo";
    TCHAR* string2 = _T("foo");
    size_t n = 5;

    int comparison = TestRunner::StringCompareCaseInsensitiveN(string1, string2, n);

    WIN_ASSERT_TRUE(comparison == 0);
}
END_TEST

// Loop ends when string1[i] != string2[i] (return: < 0)
BEGIN_TEST(StringCompareCaseInsensitiveNShouldBeCorrectForNLongerThanBothString1AndString2AndString2Greater)
{
    char* string1 = "bar";
    TCHAR* string2 = _T("foo");
    size_t n = 5;

    int comparison = TestRunner::StringCompareCaseInsensitiveN(string1, string2, n);

    WIN_ASSERT_TRUE(comparison < 0);
}
END_TEST

// Loop ends when string1[i] != string2[i] (return: > 0)
BEGIN_TEST(StringCompareCaseInsensitiveNShouldBeCorrectForNLongerThanBothString1AndString2AndString1Greater)
{
    char* string1 = "foo";
    TCHAR* string2 = _T("bar");
    size_t n = 5;

    int comparison = TestRunner::StringCompareCaseInsensitiveN(string1, string2, n);

    WIN_ASSERT_TRUE(comparison > 0);
}
END_TEST

BEGIN_TEST(StringCompareCaseInsensitiveNShouldIgnoreCase)
{
    char* string1 = "foo";
    TCHAR* string2 = _T("Food");

    int comparison1 = TestRunner::StringCompareCaseInsensitiveN(string1, string2, 3);
    WIN_ASSERT_TRUE(comparison1 == 0);

    int comparison2 = TestRunner::StringCompareCaseInsensitiveN(string1, string2, 4);
    WIN_ASSERT_TRUE(comparison2 < 0);
}
END_TEST

#pragma endregion

#pragma region Testing StringCompareExact

BEGIN_TEST(StringCompareExactShouldBeZeroForTwoEmptyStrings)
{
    char* string1 = "";
    TCHAR* string2 = _T("");

    int comparison = TestRunner::StringCompareExact(string1, string2);

    WIN_ASSERT_TRUE(comparison == 0);
}
END_TEST

BEGIN_TEST(StringCompareExactShouldBeCorrectForString1LongerThanString2WithString2PrefixOfString1)
{
    char* string1 = "FooBar";
    TCHAR* string2 = _T("Foo");

    int comparison = TestRunner::StringCompareExact(string1, string2);

    WIN_ASSERT_TRUE(comparison > 0);
}
END_TEST

BEGIN_TEST(StringCompareExactShouldBeCorrectForString2LongerThanString1WithString1PrefixOfString2)
{
    char* string1 = "Foo";
    TCHAR* string2 = _T("FooBar");

    int comparison = TestRunner::StringCompareExact(string1, string2);

    WIN_ASSERT_TRUE(comparison < 0);
}
END_TEST

BEGIN_TEST(StringCompareExactShouldNotMatchStringsThatWouldMatchCaseInsensitively)
{
    char* string1 = "FooBar";
    TCHAR* string2 = _T("Foobar");

    int comparison = TestRunner::StringCompareExact(string1, string2);

    WIN_ASSERT_TRUE(comparison != 0);
}
END_TEST

BEGIN_TEST(StringCompareExactShouldMatchNonEmptyStringsThatAreExactlyTheSame)
{
    char* string1 = "FooBar";
    TCHAR* string2 = _T("FooBar");

    int comparison = TestRunner::StringCompareExact(string1, string2);

    WIN_ASSERT_TRUE(comparison == 0);
}
END_TEST

#pragma endregion

